package online.inote.common.base;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSON;

import online.inote.common.exception.BusException;
import tk.mybatis.mapper.entity.Example;

/**
 * <p>
 * Desc: 基础Service(继承BaserService, 便拥有通用方法及事物, 默认Exception回滚事物, 如果不是可根据业务修改)
 *       T: 数据库表对应实体对象  
 *       ID: 实体类ID类型(用于以后扩展)
 * </p>
 * 
 * @author Sui
 * @created: 2017年12月2日 下午11:47:18
 * @version 1.0
 */
@Transactional(rollbackFor = BusException.class)
public class BaseService<T> {

	protected Logger logger = LoggerFactory.getLogger(getClass());
	
	protected final Class<T> CLASS;
	
	@Autowired
    protected BaseMapper<T> mapper;
	
	/**
	 * 构造方法(获取泛型)
	 */
	@SuppressWarnings("unchecked")
	public BaseService() {
        Type genType = getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        CLASS = (Class<T>) params[0];
    }
	
	/**
	  * <p>
	  * Desc: 插入
	  * </p>
	  *
	  * @author Sui
	  * @created 2017年12月3日 上午12:13:47
	  * @param t
	  * @return
	 */
	public String insert(T t) {
		logger.info("保存信息, CLASS:[ {} ], data:[ {} ]", CLASS, JSON.toJSONString(t));
		this.mapper.insertSelective(t);
		return null;
    }
	
	/**
	  * <p>
	  * Desc: 根据主键更新数据
	  * </p>
	  *
	  * @author Sui
	  * @created 2017年12月3日 上午12:14:11
	  * @param t
	  * @return
	 */
	public int updateByPrimaryKey(T t) {
		logger.info("根据主键更新数据, CLASS:[ {} ], data:[ {} ]", CLASS, JSON.toJSONString(t));
        return this.mapper.updateByPrimaryKey(t);
    }
	
	/**
	  * <p>
	  * Desc: 根据主键更新非空数据
	  * </p>
	  *
	  * @author Sui
	  * @created 2017年12月3日 上午12:15:02
	  * @param t
	  * @return
	 */
	public int updateByPrimaryKeySelective(T t){
		logger.info("根据主键更新非空数据, CLASS:[ {} ], data:[ {} ]", CLASS, JSON.toJSONString(t));
        return this.mapper.updateByPrimaryKeySelective(t);
    }
	
	/**
	  * <p>
	  * Desc: 根据主键获取对象
	  * </p>
	  *
	  * @author Sui
	  * @created 2017年12月3日 上午12:07:20
	  * @param id
	  * @return
	 */
	public T selectByPrimaryKey(String id) {
    	logger.info("根据主键获取对象, class:[ {} ], id:[ {} ]", CLASS, id);
        return this.mapper.selectByPrimaryKey(id);
    }
	
	/**
	  * <p>
	  * Desc: 根据Example查询数据(多条)
	  * </p>
	  *
	  * @author Sui
	  * @created 2017年12月3日 上午12:18:10
	  * @param e
	  * @return
	 */
	public List<T> selectListByExample(Example e){
    	logger.info("根据Example查询数据(多条), CLASS:[ {} ], Example:[ {} ]", CLASS, JSON.toJSONString(e));
        return this.mapper.selectByExample(e);
    }
	
	/**
	  * <p>
	  * Desc: 根据Example查询数据(单条)
	  * </p>
	  *
	  * @author Sui
	  * @created 2017年12月3日 上午12:24:13
	  * @param e
	  * @return
	 */
	public T selectByExample(Example e) {
    	
    	logger.info("根据Example查询数据(单条), CLASS:[ {} ], Example:[ {} ]", CLASS, JSON.toJSONString(e));
    	
        List<T> list = this.selectListByExample(e);
        
        if (CollectionUtils.isEmpty(list)) return null;
        
        if (list.size() > 1) {
            throw new BusException("根据Example查询数据(单条), 返回多条记录");
        } 
        
        return list.get(0);
    }
	
	/**
	  * <p>
	  * Desc: 根据字段值获取数据(多条)
	  * </p>
	  *
	  * @author Sui
	  * @created 2017年12月2日 下午11:56:49
	  * @param propertyName
	  * @param value
	  * @return
	  */
	public List<T> selectListByFieldEqual(String propertyName, Object value) {
		logger.info("根据字段值获取数据(多条), class:[ {} ], propertyname:[ {} ], value:[ {} ]", CLASS, propertyName, value);
        Example e = new Example(CLASS);
        e.createCriteria().andEqualTo(propertyName, value);
        return this.mapper.selectByExample(e);
	}
	
	/**
	  * <p>
	  * Desc: 根据字段值获取数据(单条)
	  * </p>
	  *
	  * @author Sui
	  * @created 2017年12月2日 下午11:56:57
	  * @param propertyName
	  * @param value
	  * @return
	 */
	public T selectByFieldEqual(String propertyName, Object value) {
		logger.info("根据字段值获取数据(单条), class:[ {} ], propertyname:[ {} ], value:[ {} ]", CLASS, propertyName, value);
		List<T> list = selectListByFieldEqual(propertyName, value);

		if (CollectionUtils.isEmpty(list)) return null;

		if (list.size() > 1) {
			throw new BusException("根据字段值获取数据(单条), 返回多条记录");
		}

		return list.get(0);
	}
	
	/**
	 * <p>
	 * Desc: 查询所有数据
	 * </p>
	 *
	 * @author XQF SUI
	 * @created 2018年1月30日 上午9:48:20
	 * @return
	 */
	public List<T> selectAll() {
		return mapper.selectAll();
	}
	
	/**
	  * <p>
	  * Desc: 根据主键删除数据
	  * </p>
	  *
	  * @author Sui
	  * @created 2017年12月3日 上午12:17:02
	  * @param id
	  * @return
	 */
	public int deleteByPrimaryKey(String id) {
    	logger.info("根据主键删除数据, CLASS:[ {} ], id:[ {} ]", CLASS, id);
        return this.mapper.deleteByPrimaryKey(id);
    }
}
